package com.smile.utils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;

public class GlobalTool {

	/**
	 * 给对象的指定字段进行赋值
	 * 
	 * @param object
	 * @param fieldName
	 * @param value
	 */
	public static void setFieldValue(Object object, String fieldName, Object value) {
		try {
			Field field = object.getClass().getDeclaredField(fieldName);
			field.setAccessible(true);
			field.set(object, value);
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获取对象的指定字段的值
	 * 
	 * @param object
	 * @param fieldName
	 */
	public static Object getFieldValue(Object object, String fieldName) {
		try {
			Field field = object.getClass().getDeclaredField(fieldName);
			field.setAccessible(true);
			return field.get(object);
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static void copyNonEmptyFields(Object from, Object to) {
		Field[] declaredFields = from.getClass().getDeclaredFields();

		try {
			for (Field field : declaredFields) {
				field.setAccessible(true);

				Object object = field.get(from);
				if (object != null) {
					field.set(to, object);
				}
			}
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}

	}

	/**
	 * 将对象转换成JSON字符串
	 * 
	 * @param o
	 * @return
	 */
	public static String toJson(Object o) {
		ObjectMapper mapper = new ObjectMapper();
		try {
			return mapper.writeValueAsString(o);
		} catch (JsonProcessingException e) {
			return "";
		}
	}

	/**
	 * 将JSON字符串转换成对象
	 * 
	 * @param o
	 * @return
	 */
	public static <T> T fromJson(String o, Class<T> c) {
		ObjectMapper mapper = new ObjectMapper();
		try {
			return mapper.readValue(o, c);
		} catch (JsonProcessingException e) {
			return null;
		} catch (IOException e) {
			return null;
		}
	}

	/**
	 * 将对象列表转换成JSON字符串，可以选择实体类仅需要的字段，或Map中仅需的Key
	 * 
	 * @param list
	 * @param includeFields
	 *            仅仅转换的字段
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static String listToJson(List list, String... includeFields) {
		if (list == null) {
			return "";
		}

		try {
			ObjectMapper objectMapper = new ObjectMapper();
			objectMapper.setSerializationInclusion(Include.NON_EMPTY);
			if (includeFields != null && includeFields.length != 0) {
				List<HashMap<String, Object>> mapList = new ArrayList<>();
				for (Object o : list) {
					Map map = convertBeanToMap(o);

					LinkedHashMap<String, Object> resultMap = new LinkedHashMap<>();
					for (String field : includeFields) {
						Object value = map.get(field);
						if (value != null) {
							resultMap.put(field, value);
						}
					}
					mapList.add(resultMap);
				}
				return objectMapper.writeValueAsString(mapList);
			} else {
				return objectMapper.writeValueAsString(list);
			}
		} catch (JsonProcessingException e) {
			return "";
		}
	}

	/**
	 * 将对象列表转换成Map类型，需要指定Key和Value字段
	 * 
	 * @param list
	 * @param keyField
	 * @param valueField
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static LinkedHashMap<String, Object> listToMap(List list, String keyField, String valueField) {
		if (list == null || StringTool.isEmpty(keyField) || StringTool.isEmpty(valueField)) {
			return new LinkedHashMap<>();
		}

		LinkedHashMap<String, Object> resultMap = new LinkedHashMap<>();
		for (Object o : list) {
			Map map = convertBeanToMap(o);

			Object key = map.get(keyField);
			Object value = map.get(valueField);
			if (key != null && value != null) {
				resultMap.put(key.toString(), value);
			}
		}
		return resultMap;
	}

	/**
	 * 将对象列表转换成Map类型的JSON字符串，需要指定Key和Value字段
	 * 
	 * @param list
	 * @param keyField
	 * @param valueField
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static String listToMapJson(List list, String keyField, String valueField) {

		try {
			ObjectMapper objectMapper = new ObjectMapper();
			objectMapper.setSerializationInclusion(Include.NON_EMPTY);
			LinkedHashMap<String, Object> resultMap = listToMap(list, keyField, valueField);
			return objectMapper.writeValueAsString(resultMap);
		} catch (JsonProcessingException e) {
			return "";
		}
	}

	/**
	 * 将对象列表转换成Map类型的JsJSON字符串，需要指定Key和Value字段
	 * 
	 * @param list
	 * @param keyField
	 * @param valueField
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static String listToMapJsJson(List list, String keyField, String valueField) {
		String result = listToMapJson(list, keyField, valueField);
		result = result.replaceAll("\\\\", "\\\\\\\\");
		result = result.replaceAll("\\'", "\\\\'");
		result = result.replaceAll("\\\"", "\\\\\"");
		return result;
	}

	/**
	 * 将一个对象转换为json字符串并对其做转义处理，使其能被直接解析 
	 * @param o
	 * @return
	 */
	public static String toJsJson(Object o) {
		String result = toJson(o);

		result = result.replaceAll("\\\\", "\\\\\\\\");
		result = result.replaceAll("\\'", "\\\\'");
		result = result.replaceAll("\\\"", "\\\\\"");
		return result;
	}

	/**
	 * 将对象列表转换成Map类型的JSON字符串，需要指定Key和Value字段
	 * 
	 * @param list
	 * @param keyField
	 * @param valueFields
	 *            不传值(null)则表示所有字段
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static String listToMapJson(List list, String keyField, String... valueFields) {
		if (list == null || StringTool.isEmpty(keyField)) {
			return "";
		}

		try {
			ObjectMapper objectMapper = new ObjectMapper();
			objectMapper.setSerializationInclusion(Include.NON_EMPTY);
			LinkedHashMap<String, LinkedHashMap<String, Object>> resultMapMap = new LinkedHashMap<>();
			for (Object o : list) {
				Map<String, Object> map = convertBeanToMap(o);

				Object key = map.get(keyField);
				if (key == null) {
					continue;
				}

				if (valueFields == null || valueFields.length == 0) {
					resultMapMap.put(key.toString(), new LinkedHashMap<>(map));
					continue;
				}

				LinkedHashMap<String, Object> resultMap = new LinkedHashMap<>();
				for (String field : valueFields) {
					Object value = map.get(field);
					if (value != null) {
						resultMap.put(field, value);
					}
				}
				resultMapMap.put(key.toString(), resultMap);
			}
			return objectMapper.writeValueAsString(resultMapMap);
		} catch (JsonProcessingException e) {
			return "";
		}
	}

	/**
	 * 将实体类中的字段和值转换为HashMap格式
	 * 
	 * @param o
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static Map<String, Object> convertBeanToMap(Object o) {
		if (o instanceof HashMap) {
			return (Map) o;
		}

		LinkedHashMap<String, Object> map = new LinkedHashMap<>();

		Field[] declaredFields = o.getClass().getDeclaredFields();

		try {
			for (Field field : declaredFields) {
				field.setAccessible(true);

				Object object = field.get(o);
				if (object != null) {
					map.put(field.getName(), object);
				}
			}
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}

		return map;
	}

	/**
	 * 取出父类和子类的所有属性
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static Map<String, Object> convertBeanAllFieldToMap(Object o) {
		if (o instanceof HashMap) {
			return (Map) o;
		}
		LinkedHashMap<String, Object> map = new LinkedHashMap<>();
		int count = 0;
		int num = 0;
		Class<? extends Object> c = o.getClass();
		while (!c.equals(Object.class)) {
			count += c.getDeclaredFields().length;
			c = c.getSuperclass();
		}
		Field[] declaredFields = new Field[count];
		c = o.getClass();
		while (!c.equals(Object.class)) {
			for (Field f : c.getDeclaredFields()) {
				declaredFields[num] = f;
				num++;
			}
			c = c.getSuperclass();
		}
		try {
			for (Field field : declaredFields) {
				field.setAccessible(true);
				Object object = field.get(o);
				if (object != null) {
					map.put(field.getName(), object);
				}
			}
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		return map;
	}

	/**
	 * 将获取到的实体类或键值对列表转换成模糊搜索select2需要的格式，id/text键值对
	 * 
	 * @param list
	 * @param idField
	 *            select2的id所对应的字段
	 * @param converter
	 *            select2的text所需的展示内容
	 * @return
	 */
	public static <T> List<HashMap<String, String>> convertSelect2List(List<T> list, String idField,
			StringConverter<T> converter) {
		if (list == null || idField == null || converter == null) {
			return new ArrayList<>();
		}

		List<HashMap<String, String>> resultList = new ArrayList<>();
		for (T o : list) {
			Map<String, Object> valueMap = convertBeanToMap(o);
			String call = converter.call(o);

			HashMap<String, String> map = new HashMap<>();
			map.put("id", String.valueOf(valueMap.get(idField)));
			map.put("text", call);
			resultList.add(map);
		}

		return resultList;
	}

	/**
	 * 将获取到的实体类或键值对列表转换成模糊搜索select2需要的格式，id/text键值对
	 * 
	 * @param list
	 * @param idField
	 *            select2的id所对应的字段
	 * @param textField
	 *            select2的text所需的展示内容
	 * @return
	 */
	public static <T> List<HashMap<String, String>> convertSelect2List(List<T> list, String idField, String textField) {
		if (list == null || idField == null || textField == null) {
			return new ArrayList<>();
		}

		List<HashMap<String, String>> resultList = new ArrayList<>();
		for (T o : list) {
			Map<String, Object> valueMap = convertBeanToMap(o);

			HashMap<String, String> map = new HashMap<>();
			map.put("id", String.valueOf(valueMap.get(idField)));
			if (StringTool.isEmpty(String.valueOf(valueMap.get(textField)))) {
				continue;
			} else {
				map.put("text", String.valueOf(valueMap.get(textField)));
			}
			resultList.add(map);
		}

		return resultList;
	}

	public static interface StringConverter<T> {
		String call(T t);
	}

	/**
	 * 输入流转字节流
	 */
	public static byte[] inputStreamToByte(InputStream is) throws IOException {
		ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int ch;
		while ((ch = is.read(buffer)) != -1) {
			bytestream.write(buffer, 0, ch);
		}
		byte data[] = bytestream.toByteArray();
		bytestream.close();
		return data;
	}

	public static String getPureFileName(String path) {
		if (StringTool.isEmpty(path)) {
			return "";
		}

		int idx1 = path.lastIndexOf("/");
		int idx2 = path.lastIndexOf("\\");

		int idx = Math.max(idx1, idx2);
		if (idx > -1) {
			return path.substring(idx + 1).trim();
		} else {
			return path.trim();
		}
	}

	/**
	 * 科学计数法字符串转换为字符串
	 * 
	 * @param val
	 * @return
	 */
	public static String toPlainString(String val) {
		String value = "";
		if (StringUtils.isEmpty(val)) {
			value = "";
		}
		if (val.indexOf(".") != -1 && val.indexOf("E") != -1) {
			BigDecimal bd = new BigDecimal(val);
			value = bd.toPlainString();
		} else {
			value = val;
		}
		return value;
	}

	/**
	 * 打印列表
	 * 
	 * @param list
	 */
	public static <E> void printList(List<E> list) {
		for (E object : list) {
			System.out.println(object);
		}
	}

	/**
	 * 打印列表
	 * 
	 * @param list
	 */
	public static <K, V> void printMap(Map<K, V> map) {
		for (Map.Entry<K, V> e : map.entrySet()) {
			System.out.println(e.getKey() + "=" + e.getValue());
		}
	}

	/**
	 * 计算两个日期之间的间隔
	 * 
	 * @param date1
	 * @param date2
	 * @return 间隔天数，0表示当天
	 */
	public static int calculateDateInterval(String date1, String date2) {
		Calendar c1 = Calendar.getInstance();
		c1.setTime(DateTimeTool.parsetDate(date1, "yyyy-MM-dd"));
		Calendar c2 = Calendar.getInstance();
		c2.setTime(DateTimeTool.parsetDate(date2, "yyyy-MM-dd"));

		System.out.println(c1);
		System.out.println(c2);

		if (c1.after(c2)) {
			Calendar c = c2;
			c2 = c1;
			c1 = c;
		}

		int count = 0;
		while (c2.after(c1)) {
			c1.add(Calendar.DAY_OF_YEAR, 1);
			count++;
		}

		return count;
	}

	/**
	 * 10进制转36进制
	 * 
	 * @param uniqueCode
	 * @return
	 */
	public static String to36(int uniqueCode) {
		String s36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

		StringBuilder sb = new StringBuilder();

		int left;
		int divide = uniqueCode;
		do {
			left = divide % 36;
			divide = divide / 36;
			sb.append(s36.charAt(left));
		} while (divide >= 36);

		if (divide > 0) {
			sb.append(s36.charAt(divide));
		}

		return sb.reverse().toString();
	}

	/**
	 * 左补0
	 * 
	 * @param text
	 * @param length
	 * @return
	 */
	public static String addLeft0(String text, int length) {
		StringBuilder sBuilder = new StringBuilder(text);
		while (sBuilder.length() < length) {
			sBuilder.insert(0, "0");
		}
		return sBuilder.toString();
	}
	
	/**
	 * json转List
	 * @param json
	 * @param c
	 * @return
	 */
	
	@SuppressWarnings("unchecked")
	public static <T> List<T>  jsonToList(String json,Class<T> c){
		ObjectMapper mapper = new ObjectMapper();
		JavaType javaType = getCollectionType(ArrayList.class, c);
		List<T> lst = null;
		try {
			lst = (List<T>)mapper.readValue(json, javaType);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return lst;
	}
	
	@SuppressWarnings("deprecation")
	private static JavaType getCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
		  ObjectMapper mapper = new ObjectMapper();
		return mapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
	}

}
